package com.surveypark.service.impl;

import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.surveypark.dao.BaseDao;
import com.surveypark.domain.Answer;
import com.surveypark.domain.Page;
import com.surveypark.domain.Question;
import com.surveypark.domain.Survey;
import com.surveypark.domain.User;
import com.surveypark.service.SurveyService;
import com.surveypark.util.DataUtil;
import com.surveypark.util.ValidateUtil;

@Service("surveyService")
public class SurveyServiceImpl extends BaseServiceImpl<Survey> implements
		SurveyService {

	@Resource(name = "surveyDao")
	private BaseDao<Survey> surveyDao;
	@Resource(name = "pageDao")
	private BaseDao<Page> pageDao;
	@Resource(name = "questionDao")
	private BaseDao<Question> questionDao;
	@Resource(name = "answerDao")
	private BaseDao<Answer> answerDao;

	@Override
	@Resource(name = "surveyDao")
	public void setDao(BaseDao<Survey> dao) {
		super.setDao(dao);
	}

	@Override
	public Survey newSurvey(User u) {
		Survey survey = new Survey();
		Page page = new Page();

		survey.setUser(u);
		survey.setLogoPhotoPath("/survey.jpg");
		page.setSurvey(survey);
		survey.getPages().add(page);

		surveyDao.saveEntity(survey);
		pageDao.saveEntity(page);
		return survey;
	}

	public List<Survey> findMySurveys(User u) {

		String hql = "from Survey s where s.user.id=?";
		return surveyDao.findEntityByHQL(hql, u.getId());

	}

	@Override
	public Survey getSurveyWithChildren(Integer sid) {
		// Survey s = surveyDao.getEntity(sid);
		Survey s = this.getSurvey(sid);
		for (Page p : s.getPages()) {
			p.getQuestions().size();
		}
		return s;
	}

	@Override
	public Survey getSurvey(Integer sid) {
		return surveyDao.getEntity(sid);
	}

	@Override
	public void updateSurvey(Survey model) {
		surveyDao.updateEntity(model);
	}

	@Override
	public void saveOrUpdatePage(Page model) {
		pageDao.saveOrUpdateEntity(model);
	}

	@Override
	public Page getPage(Integer pid) {

		return pageDao.getEntity(pid);
	}

	@Override
	public void saveOrUpdateQuestrion(Question model) {
		questionDao.saveOrUpdateEntity(model);
	}

	@Override
	public Question getQuestion(Integer qid) {
		return questionDao.getEntity(qid);
	}

	@Override
	public void deleteQuestion(Integer qid) {
		// answer
		String hql = "delete from Answer a where a.questionId = ?";
		answerDao.batchEntityByHQL(hql, qid);
		// question
		hql = "delete from Question q where q.id = ?";
		questionDao.batchEntityByHQL(hql, qid);
	}

	@Override
	public void deletePage(Integer pid) {

		// ��ɾ���
		String hql = "delete from Answer a where a.questionId in (select q.id from Question q where q.page.id = ?)";
		answerDao.batchEntityByHQL(hql, pid);

		// ɾ������
		hql = "delete from Question q where q.page.id = ?";
		questionDao.batchEntityByHQL(hql, pid);

		// ɾ��ҳ��
		hql = "delete from Page p where p.id = ?";
		pageDao.batchEntityByHQL(hql, pid);
	}

	@Override
	public void deleteSurvey(Integer sid) {

		// ɾ���
		String hql = "delete from Answer a where a.surveyId = ?";
		surveyDao.batchEntityByHQL(hql, sid);

		// ɾ������
		hql = "delete from Question q where q.page.id in (select p.id from Page p where p.survey.id = ?)";
		questionDao.batchEntityByHQL(hql, sid);

		// ɾ��ҳ��
		hql = "delete from Page p where p.survey.id = ?";
		pageDao.batchEntityByHQL(hql, sid);

		// ɾ�����
		hql = "delete from Survey s where s.id = ?";
		surveyDao.batchEntityByHQL(hql, sid);
	}

	@Override
	public void clearAnswers(Integer sid) {
		String hql = "delete from Answer a where a.surveyId = ?";
		answerDao.batchEntityByHQL(hql, sid);
	}

	@Override
	public boolean toggleStatus(Integer sid) {
		Survey s = surveyDao.getEntity(sid);
		String hql = "update Survey s set s.closed = ? where s.id = ?";
		surveyDao.batchEntityByHQL(hql, !s.isClosed(), sid);
		return s.isClosed();
	}

	@Override
	public void updateLogoPhotoPath(Integer sid, String string) {
		String hql = "update Survey s set s.logoPhotoPath = ? where id = ?";
		surveyDao.batchEntityByHQL(hql, string, sid);
	}

	@Override
	public List<Survey> findSurveysWidthPage(User user) {

		String hql = "from Survey s where s.user.id = ?";
		List<Survey> list = surveyDao.findEntityByHQL(hql, user.getId());
		for (Survey s : list) {// ǿ�г�ʼ��ҳ�漯��
			s.getPages().size();
		}
		return list;
	}

	/**
	 * �����ƶ��͸��Ʋ���
	 */
	public void moveOrCopyPage(Integer srcPid, Integer targPid, int pos) {
		Page srcPage = this.getPage(srcPid);
		Survey srcSurvey = srcPage.getSurvey();
		Page targPage = this.getPage(targPid);
		Survey targSurvey = targPage.getSurvey();
		// �ƶ�����?
		if (srcSurvey.getId().equals(targSurvey.getId())) {
			setOrderno(srcPage, targPage, pos);
		}
		// ����
		else {
			// ��Դҳ�������ȸ���
			srcPage.getQuestions().size();// ��Դҳ���е�������г�ʼ��������Ļ�Դҳ���е�������null
			Page copy = (Page) DataUtil.deeplyCopy(srcPage); // ��srcPage������ȸ���
			// �����µĹ�����ϵ
			copy.setSurvey(targSurvey);

			// �ֱ𱣴��µ�ҳ�������
			pageDao.saveEntity(copy);
			for (Question q : copy.getQuestions()) {
				questionDao.saveEntity(q);
			}
			setOrderno(copy, targPage, pos);
		}
	}

	/**
	 * ����ҳ��
	 */
	private void setOrderno(Page srcPage, Page targPage, int pos) {
		// ֮ǰ/֮��?
		if (pos == 0) {
			if (isFirstPage(targPage)) {
				srcPage.setOrderno(targPage.getOrderno() - 0.01f);
			} else {
				Page prePage = getPrePage(targPage);
				srcPage.setOrderno((targPage.getOrderno() + prePage
						.getOrderno()) / 2);
			}
		}
		// ֮��
		else {
			if (isLastPage(targPage)) {
				srcPage.setOrderno(targPage.getOrderno() + 0.01f);
			} else {
				Page nextPage = getNextPage(targPage);
				srcPage.setOrderno((targPage.getOrderno() + nextPage
						.getOrderno()) / 2);
			}
		}
	}

	/**
	 * ���ҳ�����ڵ������һҳ
	 */
	private Page getPrePage(Page targPage) {
		String hql = "from Page p where p.orderno < ? and p.survey.id = ? order by p.orderno desc";
		return pageDao.findEntityByHQL(hql,targPage.getOrderno(), targPage.getSurvey().getId()).get(0);
	}

	/**
	 * ���ҳ�����ڵ������һҳ
	 */
	private Page getNextPage(Page targPage) {
		String hql = "from Page p where p.orderno > ? and p.survey.id = ? order by p.orderno asc";
		return pageDao.findEntityByHQL(hql,

		targPage.getOrderno(), targPage.getSurvey().getId()).get(0);
	}

	/**
	 * �ж�ҳ���Ƿ������ڵ���βҳ
	 */
	private boolean isLastPage(Page targPage) {
		String hql = "from Page p where p.orderno > ? and p.survey.id = ?";
		List<Page> list = pageDao.findEntityByHQL(hql,

		targPage.getOrderno(), targPage.getSurvey().getId());
		return !ValidateUtil.isValid(list);
	}

	/**
	 * �ж�ҳ���Ƿ������ڵ�����ҳ
	 */
	private boolean isFirstPage(Page targPage) {
		String hql = "from Page p where p.orderno < ? and p.survey.id = ?";
		List<Page> list = pageDao.findEntityByHQL(hql,

		targPage.getOrderno(), targPage.getSurvey().getId());
		return !ValidateUtil.isValid(list);
	}

	@Override
	public List<Survey> findAllAvailableSurvey() {
		String hql = "from Survey s where s.closed = ?";// ��ѯ���д򿪵ĵ���
		return surveyDao.findEntityByHQL(hql, false);
	}

	@Override
	public Page getFirstPage(Integer sid) {
		String hql = "from Page p where p.survey.id=? order by p.orderno asc";
		Page p = pageDao.findEntityByHQL(hql, sid).get(0);
		p.getQuestions().size();
		p.getSurvey().getTitle();
		return p;
	}

	@Override
	public Page getPrePage(Integer currPid) {
		Page p = this.getPage(currPid);
		p = this.getPrePage(p);
		p.getQuestions().size();
		return p;
	}

	@Override
	public Page getNextPage(Integer currPid) {
		Page p = this.getPage(currPid);
		p = this.getNextPage(p);
		p.getQuestions().size();
		return p;
	}

	@Override
	public void saveAnswers(List<Answer> list) {

		String uuid = UUID.randomUUID().toString();
		Date date = new Date();
		for(Answer a:list){
			a.setUuid(uuid);
			a.setAnswerTime(date);
			answerDao.saveEntity(a);
		}
	}

	@Override
	public List<Question> getQuestions(Integer sid) {
		String hql = "from Question q where q.page.survey.id=?";
		return questionDao.findEntityByHQL(hql, sid);
	}

	@Override
	public List<Answer> findAnswers(Integer sid) {

		String hql = "from Answer a where a.surveyId=? order by a.uuid";
		return answerDao.findEntityByHQL(hql, sid);
	}
}
